package sys
//
//import (
//	"errors"
//	"fmt"
//	"net/http"
//	"reflect"
//
//	"github.com/go-spring/spring-error"
//	SpringWeb "github.com/go-spring/spring-web"
//)
//
//// contextType context.Context 的反射类型
//var contextType = reflect.TypeOf((*SpringWeb.WebContext)(nil)).Elem()
//
//// restHandler BIND 形式的 Web 处理接口
//type restHandler struct {
//	fn       interface{}
//	fnType   reflect.Type
//	fnValue  reflect.Value
//	bindType reflect.Type
//}
//
//func (b *restHandler) Invoke(ctx SpringWeb.WebContext) {
//	RpcInvoke(ctx, b.call)
//}
//
//func (b *restHandler) call(ctx SpringWeb.WebContext) interface{} {
//	// 反射创建需要绑定请求参数
//	bindVal := reflect.New(b.bindType.Elem())
//	err := ctx.Bind(bindVal.Interface())
//	SpringError.ERROR.Panic(err).When(err != nil)
//
//	// 执行处理函数，并返回结果
//	in := []reflect.Value{reflect.ValueOf(ctx), bindVal}
//	return b.fnValue.Call(in)[0].Interface()
//}
//
//func validRestFn(fnType reflect.Type) bool {
//	// 必须是函数，必须有两个入参，必须有一个返回值
//	if fnType.Kind() != reflect.Func || fnType.NumIn() != 2 || fnType.NumOut() != 1 {
//		return false
//	}
//
//	// 第一个入参必须是 SpringWeb.WebContext 类型
//	if fnType.In(0) != contextType {
//		return false
//	}
//
//	req := fnType.In(1) // 第二个入参必须是结构体指针
//	return req.Kind() == reflect.Ptr && req.Elem().Kind() == reflect.Struct
//}
//
//// REST 转换成 REST 形式的 Web 处理接口
//func REST(fn interface{}) SpringWeb.HandlerFunc {
//	if fnType := reflect.TypeOf(fn); validRestFn(fnType) {
//		h := &restHandler{
//			fn:       fn,
//			fnType:   fnType,
//			fnValue:  reflect.ValueOf(fn),
//			bindType: fnType.In(1),
//		}
//		return h.Invoke
//	}
//	panic(errors.New("fn should be func(SpringWeb.WebContext, *struct})anything"))
//}
//
//// RpcInvoke 可自定义的 rpc 执行函数
//var RpcInvoke = defaultRpcInvoke
//
//// defaultRpcInvoke 默认的 rpc 执行函数
//func defaultRpcInvoke(webCtx SpringWeb.WebContext, fn func(SpringWeb.WebContext) interface{}) {
//
//	// 目前 HTTP RPC 只能返回 json 格式的数据
//	webCtx.Header("Content-Type", "application/json")
//
//	defer func() {
//		if r := recover(); r != nil {
//			result, ok := r.(*SpringError.RpcResult)
//			if !ok {
//				var err error
//				if err, ok = r.(error); !ok {
//					err = errors.New(fmt.Sprint(r))
//				}
//				result = SpringError.ERROR.Error(err)
//			}
//			webCtx.JSON(403, result)
//		}
//	}()
//
//	result := fn(webCtx)
//	webCtx.JSON(http.StatusOK, result)
//}
